package model;

/**
 * The {@link VisiblePartsNotCachedState} class is a {@link WindowState} without a cached
 * {@link RectangularPartCollection}.
 *
 */
public class VisiblePartsNotCachedState implements WindowState{
	
	private final Window parent;

	private Window getParent() {
		return parent;
	}
	
	/**
	 * Constructor of {@link VisiblePartsNotCachedState}.
	 * @param parent is the parent {@link Window}
	 */
	public VisiblePartsNotCachedState(final Window parent) {
		this.parent = parent;
	}
	
	@Override
	public RectangularPartCollection getVisibleParts() {
		RectangularPartCollection result = new RectangularPartCollection();
		if (this.getParent().isOpen()){
			final RectangularPart meAsPart = new RectangularPart(this.getParent().getLeftUpperCorner(),this.getParent().getWidth(),this.getParent().getHeight());
			setParentWithGuaranteedHierarchy(meAsPart); 
			result.add(meAsPart);
			for(final Window currentWindow : this.getParent().getAboveMe()){
				if(currentWindow.isOpen()){
					final RectangularPartCollection newResult = new RectangularPartCollection();
					for(final RectangularPart currentPart : result.getParts()){
						if(currentPart.overlaps(currentWindow)){
							newResult.add(currentPart.getNonOverlappingArea(currentWindow));
						}
						else{
							newResult.add(currentPart);
						}
					}
					
					for(final RectangularPart p : newResult.getParts()){
						setParentWithGuaranteedHierarchy(p); 
					}
					result = newResult;
				}
			}		
		}
		this.getParent().setState(new VisiblePartsCachedState(result));
		return result;
	}

	/**
	 * Sets the parent {@link Window} of the provided {@link RectangularPart} to the
	 * parent {@link Window} of this {@link WindowState}.
	 * @param part is the {@link RectangularPart} for which the parent should be set.
	 * @throws Error if the hierarchy wasn't guarenteed.
	 */
	private void setParentWithGuaranteedHierarchy(final RectangularPart part) {
		try {
			part.setParent(this.getParent());
		} catch (final HierarchyException e) {
			throw new Error("Hierarchy shall be guaranteed!");
		}
	}
}
